/*
 * Copyright (C) 2013 Daniel Wasilew <daniel.wasilew@codeminer.org>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.codeminer.parts.update;

import org.codeminer.parts.application.ApplicationComponent;
import org.codeminer.parts.application.ApplicationContext;
import org.codeminer.parts.application.ShutdownCallback;
import org.codeminer.parts.settings.Settings;
import org.codeminer.parts.settings.SettingsListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Timer;
import java.util.TimerTask;

/**
 *
 * @author Daniel Wasilew <daniel.wasilew@codeminer.org>
 */
public class PeriodicUpdateChecker implements ApplicationComponent {

    private static Logger log = LoggerFactory.getLogger(PeriodicUpdateChecker.class);
    private Timer updateCheckTimer = new Timer("UpdateCheckTimer");
    private HttpVersionFetcher versionFetcher;
    private Settings settings;
    private ShutdownCallback shutdownCallback;
    private ApplicationContext context;

    @Override
    public void startup(final ApplicationContext context, final ShutdownCallback shutdownCallback) throws Exception {
        this.shutdownCallback = shutdownCallback;
        this.versionFetcher = new HttpVersionFetcher(context);
        this.settings = context.getApplicationPart(Settings.class);
        this.settings.addListener(settingsListener);
        this.context = context;
        scheduleUpdateChecker();
    }

    private void scheduleUpdateChecker() {
        boolean enabled = settings.isUpdateEnabled();
        if (enabled) {
            updateCheckTimer.scheduleAtFixedRate(new TimerTask() {

                @Override
                public void run() {
                    log.trace("checking for update");
                    try {
                        Version currentVersion = getCurrentVersion();
                        Version availableVersion = discoverAvailableVersion();
                        log.trace("currentVersion [{}] - availableVersion [{}]", currentVersion, availableVersion);
                        if (currentVersion.compareTo(availableVersion) < 0) {
                            log.info("new Version found");
                            fetchUpdate();
                            boolean development = context.isDevelopment();
                            if (!development) {
                                log.info("update successful downloaded. will now restart application");
                                shutdownCallback.requestShutdown("Update");
                            } else {
                                log.info("development in progress, will NOT update application");
                            }
                        }
                    } catch (UpdateException ex) {
                        log.debug("could not get update", ex);
                    }
                }
            }, 0, settings.getUpdateCheckInterval());
        } else {
            log.info("automatic update is disabled");
        }
    }

    private UpdateInformation fetchUpdate() throws UpdateException {
        return versionFetcher.fetchUpdate();
    }

    private Version getCurrentVersion() {
        return Version.current();
    }

    private Version discoverAvailableVersion() {
        return versionFetcher.getAvailableVersion();
    }

    @Override
    public void shutdown() {
    }

    @Override
    public Class getDescriptionClass() {
        return PeriodicUpdateChecker.class;
    }

    private final SettingsListener settingsListener = new SettingsListener() {
        @Override
        public void changed() {
            updateCheckTimer.cancel();
            updateCheckTimer = new Timer("UpdateCheckTimer");
            scheduleUpdateChecker();
        }
    };
}
